﻿using System;
using System.Collections.Generic;
using System.Text;
using ShootSearch.Logging;
using ShootSearch.FileSystem;

namespace ShootSearch.Indexers
{
    public class HubbleIndexer: IIndexer
    {
        public const string INSERT = "Insert {0} ({1}) values({2})";
        public const string UNIQUE_NAME = "[{0}]";
        public const string SQL_SEPARATOR = ",";
        protected HubbleIndexerConfig config;
        protected Hubble.SQLClient.SqlConnection conn;
        protected string columnNames = string.Empty;
        protected string columnValues = string.Empty;

        public HubbleIndexer()
        {
            config = new HubbleIndexerConfig();
        }

        #region IIndexer Members


        public bool Create(params object[] args)
        {
            try
            {
                if (config == null || config.InterestedAttributes.Count == 0
                    || string.IsNullOrEmpty(config.Table)) return false;

                if (conn != null)
                {
                    conn.Close();
                }

                conn = new Hubble.SQLClient.SqlConnection(config.Connection);
                conn.Open();

                List<string> names = new List<string>();
                List<string> values = new List<string>();
                for (int i = 0; i < config.InterestedAttributes.Count; i++)
                {
                    HubbleIndexerConfig.HubbleIndexerAttribute att = config.InterestedAttributes[i];
                    if (att.Name.Length > 0)
                    {
                        names.Add(string.Format(UNIQUE_NAME, att.ColumnName));
                        if (att.IsString)
                        {
                            values.Add("'{" + i + "}'");
                        }
                        else
                        {
                            values.Add("{" + i + "}");
                        
                        }
                    }
                    else 
                    {
                        return false;
                    }
                    
                }

                columnNames = string.Join(SQL_SEPARATOR, names.ToArray());
                columnValues = string.Join(SQL_SEPARATOR, values.ToArray());
                return true;
            }
            catch (Exception ex)
            {
                Log.Error(Logger, "Create error!", ex);
                return false;
            }
            
        }

        public bool Add(object doc)
        {
            string sql = string.Empty;
            bool parsed = Parse(doc, out sql);
            if (parsed)
            {
                Hubble.SQLClient.SqlCommand cmd = new Hubble.SQLClient.SqlCommand(sql, conn);
                try
                {
                    parsed = cmd.ExecuteNonQuery() == 1;
                }
                catch (Exception ex)
                {
                    parsed = false;
                    Log.Warn(Logger, "Excuting error!", ex);
                }
            }

            return parsed;
        }

       
        public void Close()
        {
            try
            {
                if (conn != null)
                {
                    conn.Close();
                }

            }
            catch (Exception ex)
            {
                Log.Warn(Logger, "Close error!", ex);                
            }
        }

        #endregion

        #region IConfigable Members


        public ShootSearch.Core.SpiderManConfig Config
        {
            get
            {
                return config;
            }
            set
            {
                if (value is HubbleIndexerConfig)
                {
                    config = value as HubbleIndexerConfig;
                }
            }
        }

        public log4net.ILog Logger { get; set; }


        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (conn != null)
            {
                conn.Close();
            }
        }

        #endregion

        protected virtual bool Parse(object input, out string sql)
        {
            sql = string.Empty;
            if (input is FileObject)
            {
                FileObjectText item = new FileObjectText((FileObject)input);
                List<string> values = new List<string>();
                for (int i = 0; i < config.InterestedAttributes.Count; i++)
                {
                    HubbleIndexerConfig.HubbleIndexerAttribute att = config.InterestedAttributes[i];
                    string value = att.ParseValue(item);
                    if (!att.AllowNull && value == null) return false;
                    if (value != null)
                    {
                        value = value.Replace("'", "\"");
                    }
                    values.Add(value); 

                }
                if (values.Count > 0)
                {
                    sql =  string.Format(INSERT,config.Table,columnNames,
                        string.Format(columnValues, values.ToArray()));

                    return true;
                }
                else return false;


            }
            else return false;
        }

    }
}
